Helper Functions
Get Only Spy Data for a specific Game
#Clean SpyData Per Game
getSpyDataWithinRangeofGame = function(spydata,game_date,range){
rangeInSeconds = 60 * 60 * range
return(filter(spydata, (date >= game_date - rangeInSeconds) & (date <= game_date + rangeInSeconds)))
}
Check if there is Spy data for a game
hasSpyDataWithinRangeOfGame = function(spydata, game_dates, range){
list = c()
for(game_date in 1:length(game_dates)){
list = append(list, nrow(getSpyDataWithinRangeofGame(spydata, game_date = game_dates[game_date], range)) != 0)
}
return(list)
}
Get Spy Data combined with Game Data for a set of Games
#Clean Spydata Per Worldcup Returns a set of spydata with their corresponding game data
getSpyAndGameDataWithinWorldcup = function(worldcup, spydata, range){
z = getSpyDataWithinRangeofGame(spydata, worldcup[[1,"Datetime"]], range)
gamerow = worldcup[1,]
for(colIndx in 1: ncol(gamerow)){
colvalue = worldcup[[1, colIndx]]
colname = colnames(worldcup)[colIndx]
z[colname] = rep(colvalue, times= nrow(z))
}
z["time.from.game"] = as.numeric(difftime(z$date, worldcup[[1,"Datetime"]],units = "secs"))
for(gameIndx in 2:nrow(worldcup)){
x = getSpyDataWithinRangeofGame(spydata, worldcup[[gameIndx,"Datetime"]], range)
gamerow = worldcup[gameIndx,]
for(colIndx in 1: ncol(gamerow)){
colvalue = worldcup[[gameIndx, colIndx]]
colname = colnames(worldcup)[colIndx]
x[colname] = rep(colvalue, times= nrow(x))
}
x["time.from.game"] = as.numeric(difftime(x$date, x$Datetime, units = "secs"))
z = union_all(z,x)
}
return(z)
}
Get Spy Data combined with Game Data for a single game
#Gives Spydata and Difference from the game time for each worldcup game
getSpyAndGameDataForOneGame = function(spydata,worldcup, game_index, range){
z = getSpyDataWithinRangeofGame(spydata, worldcup[[game_index,"Datetime"]], range)
for(colIndx in 1: ncol(worldcup[game_index,])){
colvalue = worldcup[[game_index, colIndx]]
colname = colnames(worldcup)[colIndx]
z[colname] = rep(colvalue, times= nrow(z))
}
z["time.from.game"] = as.numeric(difftime(z$date, rep(worldcup[[game_index,"Datetime"]], times = nrow(z)), units="secs"))
return(z)
}
Cleaning Data
#Update
spydata$date = as.POSIXct(spydata$date, format="%Y%m%d %H:%M:%S")
#Remove Rows containing NA's
cleaned_worldcupmatches = unique(worldcupmatches[!apply(is.na(worldcupmatches) | worldcupmatches == "", 1, all),])
#Convert Date and Time into POSIX EDT
cleaned_worldcupmatches$Datetime = as.POSIXct(cleaned_worldcupmatches$Datetime, format = "%e %b %Y - %R") - 60 * 60
#Filter Games on the Weekend
cleaned_worldcupmatches = filter(cleaned_worldcupmatches, wday(as.Date(Datetime)) != 7 & wday(as.Date(Datetime)) != 1)
#Filter Games that have no corresponding Data
cleaned_worldcupmatches = add_column(cleaned_worldcupmatches,"HasSpyData" = hasSpyDataWithinRangeOfGame(spydata, cleaned_worldcupmatches$Datetime, 3))
cleaned_worldcupmatches = filter(cleaned_worldcupmatches, cleaned_worldcupmatches$HasSpyData == TRUE)
cleaned_worldcupmatches
Get Spy Data
#Get Spy data within 3 hours of the Game For both World cups
allspydata2014 = getSpyAndGameDataWithinWorldcup(filter(cleaned_worldcupmatches, Year==2014), spydata, 3)
allspydata2010 = getSpyAndGameDataWithinWorldcup(filter(cleaned_worldcupmatches, Year==2010), spydata, 3)
Normalizing the average price
#Normalize the Data so that we can compare fairly the growth of stock price
max.2014 = max(allspydata2014$average)
max.2010 = max(allspydata2010$average)
min.2014 = min(allspydata2014$average)
min.2010 = min(allspydata2010$average)
difference.2014 = (max.2014) - (min.2014)
difference.2010 = (max.2010) - (min.2010)
normalized2014average = (allspydata2014$average-min.2014)/difference.2014
normalized2010average = (allspydata2010$average-min.2010)/difference.2010
allspydata2014 = add_column(allspydata2014, "normalized.average" = normalized2014average)
allspydata2010 = add_column(allspydata2010, "normalized.average" = normalized2010average)
allspydata = union_all(allspydata2014, allspydata2010)
allspydata
NA
Sample Games from a World Cup
set.seed(100)
samplesize = 10
worldcupmatches2014 = filter(cleaned_worldcupmatches, Year == 2014)
sampleworldcupgames = sample_n(worldcupmatches2014,size = samplesize)
print(worldcupmatches2014)
print(sampleworldcupgames)
After
game1 <- getSpyAndGameDataForOneGame(spydata, sampleworldcupgames, 1, 3)
volumesp1 <- ggplot(game1) + geom_point(mapping = aes(x=date, y=log(volume)), color ="red") + geom_vline(xintercept= sampleworldcupgames$Datetime[1]) + ggtitle("Volume over Time, Sample Game 1")
volumesp1

game2 <- getSpyAndGameDataForOneGame(spydata, sampleworldcupgames, 2, 3)
volumesp2 <- ggplot(game2) + geom_point(mapping = aes(x=date, y=log(volume)), color ="red") + geom_vline(xintercept= sampleworldcupgames$Datetime[2])+ ggtitle("Volume over Time, Sample Game 2")
volumesp2

#ERROR AGAIN WE DONT HAVE FULL DATA FOR THIS GAME
game3 <- getSpyAndGameDataForOneGame(spydata, sampleworldcupgames, 3, 3)
volumesp3 <- ggplot(game3) + geom_point(mapping = aes(x=date, y=log(volume)), color ="red") + geom_vline(xintercept= sampleworldcupgames$Datetime[3])+ ggtitle("Volume over Time, Sample Game 3")
volumesp3

game4 <- getSpyAndGameDataForOneGame(spydata, sampleworldcupgames, 4, 3)
volumesp4 <- ggplot(game4) + geom_point(mapping = aes(x=date, y=log(volume)), color ="red") + geom_vline(xintercept= sampleworldcupgames$Datetime[4])+ ggtitle("Volume over Time, Sample Game 4")
volumesp4

game5 <- getSpyAndGameDataForOneGame(spydata, sampleworldcupgames, 5, 3)
volumesp5 <- ggplot(game5) + geom_point(mapping = aes(x=date, y=log(volume)), color ="red") + geom_vline(xintercept= sampleworldcupgames$Datetime[5])+ ggtitle("Volume over Time, Sample Game 5")
volumesp5

Price Scatter Plots
Using average price
pricesp1 <- ggplot(game1) + geom_point(mapping = aes(x=date, y=average), color ="red") + geom_vline(xintercept= sampleworldcupgames$Datetime[1])+ ggtitle("Price over Time, Sample Game 1")
pricesp1

pricesp2 <- ggplot(game2) + geom_point(mapping = aes(x=date, y=average), color ="red") + geom_vline(xintercept= sampleworldcupgames$Datetime[2])+ ggtitle("Price over Time, Sample Game 2")
pricesp2

#ISSUE BECAUSE WE DONT HAVE DATA FOR 16:00 and that is time of the game
pricesp3 <- ggplot(game3) + geom_point(mapping = aes(x=date, y=average), color ="red") + geom_vline(xintercept= sampleworldcupgames$Datetime[3])+ ggtitle("Price over Time, Sample Game 3")
pricesp3

pricesp4 <- ggplot(game4) + geom_point(mapping = aes(x=date, y=average), color ="red") + geom_vline(xintercept= sampleworldcupgames$Datetime[4])+ ggtitle("Price over Time, Sample Game 4")
pricesp4

pricesp5 <- ggplot(game5, aes(date)) + geom_point(aes(y=average, ), color ="red") + geom_vline(xintercept= sampleworldcupgames$Datetime[5])+ ggtitle("Price over Time, Sample Game 5") + geom_col(aes(y=(volume))) + scale_y_continuous(sec.axis = sec_axis(~./100, name = "average"))
pricesp5

Just USA Games
worldcupmatchesUSAhome = filter(cleaned_worldcupmatches, Home.Team.Name == "USA")
worldcupmatchesUSAaway = filter(cleaned_worldcupmatches, Away.Team.Name == "USA")
worldcupmatchesUSA <- union_all(worldcupmatchesUSAaway,worldcupmatchesUSAhome)
worldcupmatchesUSA
game1USA <- getSpyAndGameDataForOneGame(spydata, worldcupmatchesUSA, 1, 3)
volumesp1USA <- ggplot(game1USA) + geom_point(mapping = aes(x=date, y=log(volume)), color ="red") + geom_vline(xintercept= worldcupmatchesUSA$Datetime[1])+ ggtitle("Volume over Time, USA Game 1, 2010")
volumesp1USA

game2USA <- getSpyAndGameDataForOneGame(spydata, worldcupmatchesUSA, 2, 3)
volumesp2USA <- ggplot(game2USA) + geom_point(mapping = aes(x=date, y=volume), color ="red") + geom_vline(xintercept= worldcupmatchesUSA$Datetime[2])+ ggtitle("Volume over Time, USA Game 2, 2014")
volumesp2USA

game3USA <- getSpyAndGameDataForOneGame(spydata, worldcupmatchesUSA, 3, 3)
volumesp3USA <- ggplot(game3USA) + geom_point(mapping = aes(x=date, y=volume), color ="red") + geom_vline(xintercept= worldcupmatchesUSA$Datetime[3])+ ggtitle("Volume over Time, USA Game 2, 2010")
volumesp3USA

game4USA <- getSpyAndGameDataForOneGame(spydata, worldcupmatchesUSA, 4, 3)
volumesp4USA <- ggplot(game4USA) + geom_point(mapping = aes(x=date, y=volume), color ="red") + geom_vline(xintercept= worldcupmatchesUSA$Datetime[4])+ ggtitle("Volume over Time, USA Game 1, 2014")
volumesp4USA

pricesp4USA <- ggplot(game4USA) + geom_point(mapping = aes(x=date, y=average), color ="red") + geom_vline(xintercept= worldcupmatchesUSA$Datetime[4])+ ggtitle("Price over Time, USA Game 1, 2014")
pricesp4USA

What time should you look to sell?
price_list = c()
time_list = c()
for (game in 1:nrow(cleaned_worldcupmatches)) {
price_game_data <- getSpyAndGameDataForOneGame(spydata, cleaned_worldcupmatches, game, 3)
highestdatapoint = price_game_data[which.max(price_game_data$average),]
highestpriceforgame <- highestdatapoint$average
time <- highestdatapoint$"time.from.game"
price_list = append(price_list, highestpriceforgame)
time_list = append(time_list, time)
}
optimal_selling.df <- data.frame("price" = price_list, "time" = time_list)
optimal_selling.df
Do THis for Optimal Buying time?
#DO THIS FOR OPTIMAL TIME TO BUY?
ggplot(optimal_selling.df) + geom_histogram(mapping = aes(x= time)) + ggtitle("How Often Best Selling Time is vs. Time From Game")

LS0tCnRpdGxlOiAiTUFUSCAzMTggRmluYWwgUHJvamVjdCIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBNQVRIIDMxOCBGaW5hbCBQcm9qZWN0OiBUaGUgRWZmZWN0IG9mIFdvcmxkIEN1cCBvbiBTdG9jayBQcmljZSBhbmQgVHJhZGluZyBBY3Rpdml0eQoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KE1BU1MpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkoR0dhbGx5KQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmBgYAoKIyBMb2FkIERhdGEKCmBgYHtyfQpzcHlkYXRhID0gYXNfdGliYmxlKHJlYWQuY3N2KCIxX21pbl9TUFlfMjAwOC0yMDIxLmNzdiIpKQpgYGAKCmBgYHtyfQp3b3JsZGN1cG1hdGNoZXMgPSBhc190aWJibGUocmVhZC5jc3YoIldvcmxkQ3VwTWF0Y2hlcy5jc3YiKSkKYGBgCgojIEhlbHBlciBGdW5jdGlvbnMKCiMjIEdldCBPbmx5IFNweSBEYXRhIGZvciBhIHNwZWNpZmljIEdhbWUKCmBgYHtyfQojQ2xlYW4gU3B5RGF0YSBQZXIgR2FtZQpnZXRTcHlEYXRhV2l0aGluUmFuZ2VvZkdhbWUgPSBmdW5jdGlvbihzcHlkYXRhLGdhbWVfZGF0ZSxyYW5nZSl7CiAgcmFuZ2VJblNlY29uZHMgPSA2MCAqIDYwICogcmFuZ2UKICByZXR1cm4oZmlsdGVyKHNweWRhdGEsIChkYXRlID49IGdhbWVfZGF0ZSAtIHJhbmdlSW5TZWNvbmRzKSAmIChkYXRlIDw9IGdhbWVfZGF0ZSArIHJhbmdlSW5TZWNvbmRzKSkpCn0KYGBgCgojIyBDaGVjayBpZiB0aGVyZSBpcyBTcHkgZGF0YSBmb3IgYSBnYW1lCgpgYGB7cn0KaGFzU3B5RGF0YVdpdGhpblJhbmdlT2ZHYW1lID0gZnVuY3Rpb24oc3B5ZGF0YSwgZ2FtZV9kYXRlcywgcmFuZ2UpewogIGxpc3QgPSBjKCkKICBmb3IoZ2FtZV9kYXRlIGluIDE6bGVuZ3RoKGdhbWVfZGF0ZXMpKXsKICAgIGxpc3QgPSBhcHBlbmQobGlzdCwgbnJvdyhnZXRTcHlEYXRhV2l0aGluUmFuZ2VvZkdhbWUoc3B5ZGF0YSwgZ2FtZV9kYXRlID0gZ2FtZV9kYXRlc1tnYW1lX2RhdGVdLCByYW5nZSkpICE9IDApCiAgfQogIHJldHVybihsaXN0KQp9CmBgYAoKIyMgR2V0IFNweSBEYXRhIGNvbWJpbmVkIHdpdGggR2FtZSBEYXRhIGZvciBhIHNldCBvZiBHYW1lcwoKYGBge3J9CiNDbGVhbiBTcHlkYXRhIFBlciBXb3JsZGN1cCBSZXR1cm5zIGEgc2V0IG9mIHNweWRhdGEgd2l0aCB0aGVpciBjb3JyZXNwb25kaW5nIGdhbWUgZGF0YQpnZXRTcHlBbmRHYW1lRGF0YVdpdGhpbldvcmxkY3VwID0gZnVuY3Rpb24od29ybGRjdXAsIHNweWRhdGEsIHJhbmdlKXsKICB6ID0gZ2V0U3B5RGF0YVdpdGhpblJhbmdlb2ZHYW1lKHNweWRhdGEsIHdvcmxkY3VwW1sxLCJEYXRldGltZSJdXSwgcmFuZ2UpCiAgZ2FtZXJvdyA9IHdvcmxkY3VwWzEsXQogIGZvcihjb2xJbmR4IGluIDE6IG5jb2woZ2FtZXJvdykpewogICAgICBjb2x2YWx1ZSA9IHdvcmxkY3VwW1sxLCBjb2xJbmR4XV0KICAgICAgY29sbmFtZSA9IGNvbG5hbWVzKHdvcmxkY3VwKVtjb2xJbmR4XQogICAgICB6W2NvbG5hbWVdID0gcmVwKGNvbHZhbHVlLCB0aW1lcz0gbnJvdyh6KSkKICB9CiAgelsidGltZS5mcm9tLmdhbWUiXSA9IGFzLm51bWVyaWMoZGlmZnRpbWUoeiRkYXRlLCB3b3JsZGN1cFtbMSwiRGF0ZXRpbWUiXV0sdW5pdHMgPSAic2VjcyIpKQogIGZvcihnYW1lSW5keCBpbiAyOm5yb3cod29ybGRjdXApKXsKICAgeCA9IGdldFNweURhdGFXaXRoaW5SYW5nZW9mR2FtZShzcHlkYXRhLCB3b3JsZGN1cFtbZ2FtZUluZHgsIkRhdGV0aW1lIl1dLCByYW5nZSkKICAgZ2FtZXJvdyA9IHdvcmxkY3VwW2dhbWVJbmR4LF0KICAgZm9yKGNvbEluZHggaW4gMTogbmNvbChnYW1lcm93KSl7CiAgICAgIGNvbHZhbHVlID0gd29ybGRjdXBbW2dhbWVJbmR4LCBjb2xJbmR4XV0KICAgICAgY29sbmFtZSA9IGNvbG5hbWVzKHdvcmxkY3VwKVtjb2xJbmR4XQogICAgICB4W2NvbG5hbWVdID0gcmVwKGNvbHZhbHVlLCB0aW1lcz0gbnJvdyh4KSkKICAgfQogICB4WyJ0aW1lLmZyb20uZ2FtZSJdID0gYXMubnVtZXJpYyhkaWZmdGltZSh4JGRhdGUsIHgkRGF0ZXRpbWUsIHVuaXRzID0gInNlY3MiKSkKICAKICAgeiA9IHVuaW9uX2FsbCh6LHgpCiAgfQogIHJldHVybih6KQp9CmBgYAoKIyMgR2V0IFNweSBEYXRhIGNvbWJpbmVkIHdpdGggR2FtZSBEYXRhIGZvciBhIHNpbmdsZSBnYW1lCgpgYGB7cn0KI0dpdmVzIFNweWRhdGEgYW5kIERpZmZlcmVuY2UgZnJvbSB0aGUgZ2FtZSB0aW1lIGZvciBlYWNoIHdvcmxkY3VwIGdhbWUKZ2V0U3B5QW5kR2FtZURhdGFGb3JPbmVHYW1lID0gZnVuY3Rpb24oc3B5ZGF0YSx3b3JsZGN1cCwgZ2FtZV9pbmRleCwgcmFuZ2UpewogIHogPSBnZXRTcHlEYXRhV2l0aGluUmFuZ2VvZkdhbWUoc3B5ZGF0YSwgd29ybGRjdXBbW2dhbWVfaW5kZXgsIkRhdGV0aW1lIl1dLCByYW5nZSkKICBmb3IoY29sSW5keCBpbiAxOiBuY29sKHdvcmxkY3VwW2dhbWVfaW5kZXgsXSkpewogICAgICBjb2x2YWx1ZSA9IHdvcmxkY3VwW1tnYW1lX2luZGV4LCBjb2xJbmR4XV0KICAgICAgY29sbmFtZSA9IGNvbG5hbWVzKHdvcmxkY3VwKVtjb2xJbmR4XQogICAgICB6W2NvbG5hbWVdID0gcmVwKGNvbHZhbHVlLCB0aW1lcz0gbnJvdyh6KSkKICB9CiAgelsidGltZS5mcm9tLmdhbWUiXSA9IGFzLm51bWVyaWMoZGlmZnRpbWUoeiRkYXRlLCByZXAod29ybGRjdXBbW2dhbWVfaW5kZXgsIkRhdGV0aW1lIl1dLCB0aW1lcyA9IG5yb3coeikpLCB1bml0cz0ic2VjcyIpKQogIHJldHVybih6KQp9CmBgYAoKIyBDbGVhbmluZyBEYXRhCgpgYGB7cn0KI1VwZGF0ZSAKc3B5ZGF0YSRkYXRlID0gYXMuUE9TSVhjdChzcHlkYXRhJGRhdGUsIGZvcm1hdD0iJVklbSVkICVIOiVNOiVTIikKCiNSZW1vdmUgUm93cyBjb250YWluaW5nIE5BJ3MKY2xlYW5lZF93b3JsZGN1cG1hdGNoZXMgPSB1bmlxdWUod29ybGRjdXBtYXRjaGVzWyFhcHBseShpcy5uYSh3b3JsZGN1cG1hdGNoZXMpIHwgd29ybGRjdXBtYXRjaGVzID09ICIiLCAxLCBhbGwpLF0pCgojQ29udmVydCBEYXRlIGFuZCBUaW1lIGludG8gUE9TSVggRURUIApjbGVhbmVkX3dvcmxkY3VwbWF0Y2hlcyREYXRldGltZSA9IGFzLlBPU0lYY3QoY2xlYW5lZF93b3JsZGN1cG1hdGNoZXMkRGF0ZXRpbWUsIGZvcm1hdCA9ICIlZSAlYiAlWSAtICVSIikgLSA2MCAqIDYwCgojRmlsdGVyIEdhbWVzIG9uIHRoZSBXZWVrZW5kCmNsZWFuZWRfd29ybGRjdXBtYXRjaGVzID0gZmlsdGVyKGNsZWFuZWRfd29ybGRjdXBtYXRjaGVzLCB3ZGF5KGFzLkRhdGUoRGF0ZXRpbWUpKSAhPSA3ICYgd2RheShhcy5EYXRlKERhdGV0aW1lKSkgIT0gMSkKCiNGaWx0ZXIgR2FtZXMgdGhhdCBoYXZlIG5vIGNvcnJlc3BvbmRpbmcgRGF0YQpjbGVhbmVkX3dvcmxkY3VwbWF0Y2hlcyA9IGFkZF9jb2x1bW4oY2xlYW5lZF93b3JsZGN1cG1hdGNoZXMsIkhhc1NweURhdGEiID0gaGFzU3B5RGF0YVdpdGhpblJhbmdlT2ZHYW1lKHNweWRhdGEsIGNsZWFuZWRfd29ybGRjdXBtYXRjaGVzJERhdGV0aW1lLCAzKSkKY2xlYW5lZF93b3JsZGN1cG1hdGNoZXMgPSBmaWx0ZXIoY2xlYW5lZF93b3JsZGN1cG1hdGNoZXMsIGNsZWFuZWRfd29ybGRjdXBtYXRjaGVzJEhhc1NweURhdGEgPT0gVFJVRSkKCmNsZWFuZWRfd29ybGRjdXBtYXRjaGVzCmBgYAoKIyMgR2V0IFNweSBEYXRhCgpgYGB7cn0KI0dldCBTcHkgZGF0YSB3aXRoaW4gMyBob3VycyBvZiB0aGUgR2FtZSBGb3IgYm90aCBXb3JsZCBjdXBzCmFsbHNweWRhdGEyMDE0ID0gZ2V0U3B5QW5kR2FtZURhdGFXaXRoaW5Xb3JsZGN1cChmaWx0ZXIoY2xlYW5lZF93b3JsZGN1cG1hdGNoZXMsIFllYXI9PTIwMTQpLCBzcHlkYXRhLCAzKQoKYWxsc3B5ZGF0YTIwMTAgPSBnZXRTcHlBbmRHYW1lRGF0YVdpdGhpbldvcmxkY3VwKGZpbHRlcihjbGVhbmVkX3dvcmxkY3VwbWF0Y2hlcywgWWVhcj09MjAxMCksIHNweWRhdGEsIDMpCgpgYGAKCiMjIE5vcm1hbGl6aW5nIHRoZSBhdmVyYWdlIHByaWNlCgpgYGB7cn0KI05vcm1hbGl6ZSB0aGUgRGF0YSBzbyB0aGF0IHdlIGNhbiBjb21wYXJlIGZhaXJseSB0aGUgZ3Jvd3RoIG9mIHN0b2NrIHByaWNlCm1heC4yMDE0ID0gbWF4KGFsbHNweWRhdGEyMDE0JGF2ZXJhZ2UpCm1heC4yMDEwID0gbWF4KGFsbHNweWRhdGEyMDEwJGF2ZXJhZ2UpCgoKbWluLjIwMTQgPSBtaW4oYWxsc3B5ZGF0YTIwMTQkYXZlcmFnZSkKbWluLjIwMTAgPSBtaW4oYWxsc3B5ZGF0YTIwMTAkYXZlcmFnZSkKCmRpZmZlcmVuY2UuMjAxNCA9IChtYXguMjAxNCkgLSAobWluLjIwMTQpCmRpZmZlcmVuY2UuMjAxMCA9IChtYXguMjAxMCkgLSAobWluLjIwMTApCm5vcm1hbGl6ZWQyMDE0YXZlcmFnZSA9IChhbGxzcHlkYXRhMjAxNCRhdmVyYWdlLW1pbi4yMDE0KS9kaWZmZXJlbmNlLjIwMTQKbm9ybWFsaXplZDIwMTBhdmVyYWdlID0gKGFsbHNweWRhdGEyMDEwJGF2ZXJhZ2UtbWluLjIwMTApL2RpZmZlcmVuY2UuMjAxMAoKCmFsbHNweWRhdGEyMDE0ID0gYWRkX2NvbHVtbihhbGxzcHlkYXRhMjAxNCwgIm5vcm1hbGl6ZWQuYXZlcmFnZSIgPSBub3JtYWxpemVkMjAxNGF2ZXJhZ2UpCmFsbHNweWRhdGEyMDEwID0gYWRkX2NvbHVtbihhbGxzcHlkYXRhMjAxMCwgIm5vcm1hbGl6ZWQuYXZlcmFnZSIgPSBub3JtYWxpemVkMjAxMGF2ZXJhZ2UpCgphbGxzcHlkYXRhID0gdW5pb25fYWxsKGFsbHNweWRhdGEyMDE0LCBhbGxzcHlkYXRhMjAxMCkKCmFsbHNweWRhdGEKCmBgYAoKIyMgCgojIEV4cGxvcmluZyB0aGUgUmVsYXRpb25zaGlwIG9mIFRpbWUgYW5kIFZvbHVtZQoKTGV0IHVzIGV4cGxvcmUgdGhlIENvcnJlbGF0aW9uIGJldHdlZW4gdGhlIFRpbWUgZm9ybSBnYW1lIGFuZCB0aGUgUHJpY2Ugb2YgdGhlIHN0b2NrCgojIyBDb3JyZWxhdGlvbnMKCmBgYHtyfQpnZ3BhaXJzKGFsbHNweWRhdGEsIGNvbHVtbnMgPSBjKCJ0aW1lLmZyb20uZ2FtZSIsICJhdmVyYWdlIiwgInZvbHVtZSIsICJub3JtYWxpemVkLmF2ZXJhZ2UiKSkKYGBgCgpgYGB7cn0Ka2FibGUoY29yKGFsbHNweWRhdGFbLCBjKDcsOSwzMSwzMildKSkKYGBgCgojIyBMaW5lYXIgUmVncmVzc2lvbgoKYGBge3J9CmdncGxvdChhbGxzcHlkYXRhKSArIGdlb21fcG9pbnQoYWVzKHRpbWUuZnJvbS5nYW1lLG5vcm1hbGl6ZWQuYXZlcmFnZSkpCmBgYAoKYGBge3J9CmdncGxvdChhbGxzcHlkYXRhLCBhZXModGltZS5mcm9tLmdhbWUsbG9nKHZvbHVtZSkpKSArIGdlb21fcG9pbnQoKSArIGdlb21fc21vb3RoKCkKCmBgYAoKIyBTYW1wbGUgR2FtZXMgZnJvbSBhIFdvcmxkIEN1cAoKYGBge3J9CnNldC5zZWVkKDEwMCkgCnNhbXBsZXNpemUgPSAxMAp3b3JsZGN1cG1hdGNoZXMyMDE0ID0gZmlsdGVyKGNsZWFuZWRfd29ybGRjdXBtYXRjaGVzLCBZZWFyID09IDIwMTQpCnNhbXBsZXdvcmxkY3VwZ2FtZXMgPSBzYW1wbGVfbih3b3JsZGN1cG1hdGNoZXMyMDE0LHNpemUgPSBzYW1wbGVzaXplKQpgYGAKCkFmdGVyCgpgYGB7cn0KZ2FtZTEgPC0gZ2V0U3B5QW5kR2FtZURhdGFGb3JPbmVHYW1lKHNweWRhdGEsIHNhbXBsZXdvcmxkY3VwZ2FtZXMsIDEsIDMpCnZvbHVtZXNwMSA8LSBnZ3Bsb3QoZ2FtZTEpICsgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHg9ZGF0ZSwgeT1sb2codm9sdW1lKSksIGNvbG9yID0icmVkIikgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9IHNhbXBsZXdvcmxkY3VwZ2FtZXMkRGF0ZXRpbWVbMV0pICsgZ2d0aXRsZSgiVm9sdW1lIG92ZXIgVGltZSwgU2FtcGxlIEdhbWUgMSIpCnZvbHVtZXNwMQpgYGAKCmBgYHtyfQpnYW1lMiA8LSBnZXRTcHlBbmRHYW1lRGF0YUZvck9uZUdhbWUoc3B5ZGF0YSwgc2FtcGxld29ybGRjdXBnYW1lcywgMiwgMykKdm9sdW1lc3AyIDwtIGdncGxvdChnYW1lMikgKyBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeD1kYXRlLCB5PWxvZyh2b2x1bWUpKSwgY29sb3IgPSJyZWQiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD0gc2FtcGxld29ybGRjdXBnYW1lcyREYXRldGltZVsyXSkrIGdndGl0bGUoIlZvbHVtZSBvdmVyIFRpbWUsIFNhbXBsZSBHYW1lIDIiKQp2b2x1bWVzcDIKI0VSUk9SIEFHQUlOIFdFIERPTlQgSEFWRSBGVUxMIERBVEEgRk9SIFRISVMgR0FNRQpgYGAKCmBgYHtyfQpnYW1lMyA8LSBnZXRTcHlBbmRHYW1lRGF0YUZvck9uZUdhbWUoc3B5ZGF0YSwgc2FtcGxld29ybGRjdXBnYW1lcywgMywgMykKdm9sdW1lc3AzIDwtIGdncGxvdChnYW1lMykgKyBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeD1kYXRlLCB5PWxvZyh2b2x1bWUpKSwgY29sb3IgPSJyZWQiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD0gc2FtcGxld29ybGRjdXBnYW1lcyREYXRldGltZVszXSkrIGdndGl0bGUoIlZvbHVtZSBvdmVyIFRpbWUsIFNhbXBsZSBHYW1lIDMiKQp2b2x1bWVzcDMKYGBgCgpgYGB7cn0KZ2FtZTQgPC0gZ2V0U3B5QW5kR2FtZURhdGFGb3JPbmVHYW1lKHNweWRhdGEsIHNhbXBsZXdvcmxkY3VwZ2FtZXMsIDQsIDMpCnZvbHVtZXNwNCA8LSBnZ3Bsb3QoZ2FtZTQpICsgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHg9ZGF0ZSwgeT1sb2codm9sdW1lKSksIGNvbG9yID0icmVkIikgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9IHNhbXBsZXdvcmxkY3VwZ2FtZXMkRGF0ZXRpbWVbNF0pKyBnZ3RpdGxlKCJWb2x1bWUgb3ZlciBUaW1lLCBTYW1wbGUgR2FtZSA0IikKdm9sdW1lc3A0CmBgYAoKYGBge3J9CmdhbWU1IDwtIGdldFNweUFuZEdhbWVEYXRhRm9yT25lR2FtZShzcHlkYXRhLCBzYW1wbGV3b3JsZGN1cGdhbWVzLCA1LCAzKQp2b2x1bWVzcDUgPC0gZ2dwbG90KGdhbWU1KSArIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4PWRhdGUsIHk9bG9nKHZvbHVtZSkpLCBjb2xvciA9InJlZCIpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0PSBzYW1wbGV3b3JsZGN1cGdhbWVzJERhdGV0aW1lWzVdKSsgZ2d0aXRsZSgiVm9sdW1lIG92ZXIgVGltZSwgU2FtcGxlIEdhbWUgNSIpCnZvbHVtZXNwNQpgYGAKCiMjIFByaWNlIFNjYXR0ZXIgUGxvdHMKClVzaW5nIGF2ZXJhZ2UgcHJpY2UKCmBgYHtyfQpwcmljZXNwMSA8LSBnZ3Bsb3QoZ2FtZTEpICsgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHg9ZGF0ZSwgeT1hdmVyYWdlKSwgY29sb3IgPSJyZWQiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD0gc2FtcGxld29ybGRjdXBnYW1lcyREYXRldGltZVsxXSkrIGdndGl0bGUoIlByaWNlIG92ZXIgVGltZSwgU2FtcGxlIEdhbWUgMSIpCnByaWNlc3AxCmBgYAoKYGBge3J9CnByaWNlc3AyIDwtIGdncGxvdChnYW1lMikgKyBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeD1kYXRlLCB5PWF2ZXJhZ2UpLCBjb2xvciA9InJlZCIpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0PSBzYW1wbGV3b3JsZGN1cGdhbWVzJERhdGV0aW1lWzJdKSsgZ2d0aXRsZSgiUHJpY2Ugb3ZlciBUaW1lLCBTYW1wbGUgR2FtZSAyIikKcHJpY2VzcDIKI0lTU1VFIEJFQ0FVU0UgV0UgRE9OVCBIQVZFIERBVEEgRk9SIDE2OjAwIGFuZCB0aGF0IGlzIHRpbWUgb2YgdGhlIGdhbWUKYGBgCgpgYGB7cn0KcHJpY2VzcDMgPC0gZ2dwbG90KGdhbWUzKSArIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4PWRhdGUsIHk9YXZlcmFnZSksIGNvbG9yID0icmVkIikgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9IHNhbXBsZXdvcmxkY3VwZ2FtZXMkRGF0ZXRpbWVbM10pKyBnZ3RpdGxlKCJQcmljZSBvdmVyIFRpbWUsIFNhbXBsZSBHYW1lIDMiKQpwcmljZXNwMwpgYGAKCmBgYHtyfQpwcmljZXNwNCA8LSBnZ3Bsb3QoZ2FtZTQpICsgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHg9ZGF0ZSwgeT1hdmVyYWdlKSwgY29sb3IgPSJyZWQiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD0gc2FtcGxld29ybGRjdXBnYW1lcyREYXRldGltZVs0XSkrIGdndGl0bGUoIlByaWNlIG92ZXIgVGltZSwgU2FtcGxlIEdhbWUgNCIpCnByaWNlc3A0CmBgYAoKYGBge3J9CnByaWNlc3A1IDwtIGdncGxvdChnYW1lNSwgYWVzKGRhdGUpKSArIGdlb21fcG9pbnQoYWVzKHk9YXZlcmFnZSwgKSwgY29sb3IgPSJyZWQiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD0gc2FtcGxld29ybGRjdXBnYW1lcyREYXRldGltZVs1XSkrIGdndGl0bGUoIlByaWNlIG92ZXIgVGltZSwgU2FtcGxlIEdhbWUgNSIpICsgZ2VvbV9jb2woYWVzKHk9KHZvbHVtZSkpKSArIHNjYWxlX3lfY29udGludW91cyhzZWMuYXhpcyA9IHNlY19heGlzKH4uLzEwMCwgbmFtZSA9ICJhdmVyYWdlIikpCnByaWNlc3A1CmBgYAoKIyMgSnVzdCBVU0EgR2FtZXMKCmBgYHtyfQp3b3JsZGN1cG1hdGNoZXNVU0Fob21lID0gZmlsdGVyKGNsZWFuZWRfd29ybGRjdXBtYXRjaGVzLCBIb21lLlRlYW0uTmFtZSA9PSAiVVNBIikKd29ybGRjdXBtYXRjaGVzVVNBYXdheSA9IGZpbHRlcihjbGVhbmVkX3dvcmxkY3VwbWF0Y2hlcywgQXdheS5UZWFtLk5hbWUgPT0gIlVTQSIpCndvcmxkY3VwbWF0Y2hlc1VTQSA8LSB1bmlvbl9hbGwod29ybGRjdXBtYXRjaGVzVVNBYXdheSx3b3JsZGN1cG1hdGNoZXNVU0Fob21lKQp3b3JsZGN1cG1hdGNoZXNVU0EKYGBgCgpgYGB7cn0KZ2FtZTFVU0EgPC0gZ2V0U3B5QW5kR2FtZURhdGFGb3JPbmVHYW1lKHNweWRhdGEsIHdvcmxkY3VwbWF0Y2hlc1VTQSwgMSwgMykKdm9sdW1lc3AxVVNBIDwtIGdncGxvdChnYW1lMVVTQSkgKyBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeD1kYXRlLCB5PWxvZyh2b2x1bWUpKSwgY29sb3IgPSJyZWQiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD0gd29ybGRjdXBtYXRjaGVzVVNBJERhdGV0aW1lWzFdKSsgZ2d0aXRsZSgiVm9sdW1lIG92ZXIgVGltZSwgVVNBIEdhbWUgMSwgMjAxMCIpCnZvbHVtZXNwMVVTQQpgYGAKCmBgYHtyfQpnYW1lMlVTQSA8LSBnZXRTcHlBbmRHYW1lRGF0YUZvck9uZUdhbWUoc3B5ZGF0YSwgd29ybGRjdXBtYXRjaGVzVVNBLCAyLCAzKQp2b2x1bWVzcDJVU0EgPC0gZ2dwbG90KGdhbWUyVVNBKSArIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4PWRhdGUsIHk9bG9nKHZvbHVtZSkpLCBjb2xvciA9InJlZCIpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0PSB3b3JsZGN1cG1hdGNoZXNVU0EkRGF0ZXRpbWVbMl0pKyBnZ3RpdGxlKCJWb2x1bWUgb3ZlciBUaW1lLCBVU0EgR2FtZSAyLCAyMDE0IikKdm9sdW1lc3AyVVNBCmBgYAoKYGBge3J9CmdhbWUzVVNBIDwtIGdldFNweUFuZEdhbWVEYXRhRm9yT25lR2FtZShzcHlkYXRhLCB3b3JsZGN1cG1hdGNoZXNVU0EsIDMsIDMpCnZvbHVtZXNwM1VTQSA8LSBnZ3Bsb3QoZ2FtZTNVU0EpICsgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHg9ZGF0ZSwgeT12b2x1bWUpLCBjb2xvciA9InJlZCIpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0PSB3b3JsZGN1cG1hdGNoZXNVU0EkRGF0ZXRpbWVbM10pKyBnZ3RpdGxlKCJWb2x1bWUgb3ZlciBUaW1lLCBVU0EgR2FtZSAyLCAyMDEwIikKdm9sdW1lc3AzVVNBCmBgYAoKYGBge3J9CmdhbWU0VVNBIDwtIGdldFNweUFuZEdhbWVEYXRhRm9yT25lR2FtZShzcHlkYXRhLCB3b3JsZGN1cG1hdGNoZXNVU0EsIDQsIDMpCnZvbHVtZXNwNFVTQSA8LSBnZ3Bsb3QoZ2FtZTRVU0EpICsgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHg9ZGF0ZSwgeT12b2x1bWUpLCBjb2xvciA9InJlZCIpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0PSB3b3JsZGN1cG1hdGNoZXNVU0EkRGF0ZXRpbWVbNF0pKyBnZ3RpdGxlKCJWb2x1bWUgb3ZlciBUaW1lLCBVU0EgR2FtZSAxLCAyMDE0IikKdm9sdW1lc3A0VVNBCmBgYAoKYGBge3J9CnByaWNlc3A0VVNBIDwtIGdncGxvdChnYW1lNFVTQSkgKyBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeD1kYXRlLCB5PWF2ZXJhZ2UpLCBjb2xvciA9InJlZCIpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0PSB3b3JsZGN1cG1hdGNoZXNVU0EkRGF0ZXRpbWVbNF0pKyBnZ3RpdGxlKCJQcmljZSBvdmVyIFRpbWUsIFVTQSBHYW1lIDEsIDIwMTQiKQpwcmljZXNwNFVTQQpgYGAKCiMgSXMgdGhlcmUgYSB3YXkgdG8gbWFrZSBtb25leSBkdXJpbmcgV29ybGQgQ3VwIEdhbWVzPwoKIyBXaGF0IHRpbWUgc2hvdWxkIHlvdSBsb29rIHRvIHNlbGw/CgpgYGB7cn0KcHJpY2VfbGlzdCA9IGMoKQp0aW1lX2xpc3QgPSBjKCkKZm9yIChnYW1lIGluIDE6bnJvdyhjbGVhbmVkX3dvcmxkY3VwbWF0Y2hlcykpIHsKICBwcmljZV9nYW1lX2RhdGEgPC0gZ2V0U3B5QW5kR2FtZURhdGFGb3JPbmVHYW1lKHNweWRhdGEsIGNsZWFuZWRfd29ybGRjdXBtYXRjaGVzLCBnYW1lLCAzKQogIGhpZ2hlc3RkYXRhcG9pbnQgPSBwcmljZV9nYW1lX2RhdGFbd2hpY2gubWF4KHByaWNlX2dhbWVfZGF0YSRhdmVyYWdlKSxdCiAgaGlnaGVzdHByaWNlZm9yZ2FtZSA8LSBoaWdoZXN0ZGF0YXBvaW50JGF2ZXJhZ2UKICB0aW1lIDwtIGhpZ2hlc3RkYXRhcG9pbnQkInRpbWUuZnJvbS5nYW1lIgogIHByaWNlX2xpc3QgPSBhcHBlbmQocHJpY2VfbGlzdCwgaGlnaGVzdHByaWNlZm9yZ2FtZSkKICB0aW1lX2xpc3QgPSBhcHBlbmQodGltZV9saXN0LCB0aW1lKQp9CmBgYAoKYGBge3J9Cm9wdGltYWxfc2VsbGluZy5kZiA8LSBkYXRhLmZyYW1lKCJwcmljZSIgPSBwcmljZV9saXN0LCAidGltZSIgPSB0aW1lX2xpc3QpCm9wdGltYWxfc2VsbGluZy5kZgpgYGAKCkRvIFRIaXMgZm9yIE9wdGltYWwgQnV5aW5nIHRpbWU/CgpgYGB7cn0KZ2dwbG90KG9wdGltYWxfc2VsbGluZy5kZikgKyBnZW9tX2hpc3RvZ3JhbShtYXBwaW5nID0gYWVzKHg9IHRpbWUpKSArIGdndGl0bGUoIkhvdyBPZnRlbiBCZXN0IFNlbGxpbmcgVGltZSBpcyB2cy4gVGltZSBGcm9tIEdhbWUiKQpgYGAKCiMgV2hhdCB0aW1lIHNob3VsZCB5b3UgbG9vayB0byBidXk/CgpgYGB7cn0KcHJpY2VfbGlzdCA9IGMoKQp0aW1lX2xpc3QgPSBjKCkKZm9yIChnYW1lIGluIDE6bnJvdyhjbGVhbmVkX3dvcmxkY3VwbWF0Y2hlcykpIHsKICBwcmljZV9nYW1lX2RhdGEgPC0gZ2V0U3B5QW5kR2FtZURhdGFGb3JPbmVHYW1lKHNweWRhdGEsIGNsZWFuZWRfd29ybGRjdXBtYXRjaGVzLCBnYW1lLCAzKQogIGxvd2VzdGRhdGFwb2ludCA9IHByaWNlX2dhbWVfZGF0YVt3aGljaC5taW4ocHJpY2VfZ2FtZV9kYXRhJGF2ZXJhZ2UpLF0KICBsb3dlc3RwcmljZWZvcmdhbWUgPC0gbG93ZXN0ZGF0YXBvaW50JGF2ZXJhZ2UKICB0aW1lIDwtIGxvd2VzdGRhdGFwb2ludCQidGltZS5mcm9tLmdhbWUiCiAgcHJpY2VfbGlzdCA9IGFwcGVuZChwcmljZV9saXN0LCBsb3dlc3RwcmljZWZvcmdhbWUpCiAgdGltZV9saXN0ID0gYXBwZW5kKHRpbWVfbGlzdCwgdGltZSkKfQpgYGAKCmBgYHtyfQpvcHRpbWFsX2J1eWluZy5kZiA8LSBkYXRhLmZyYW1lKCJwcmljZSIgPSBwcmljZV9saXN0LCAidGltZSIgPSB0aW1lX2xpc3QpCmdncGxvdChvcHRpbWFsX2J1eWluZy5kZikgKyBnZW9tX2hpc3RvZ3JhbShtYXBwaW5nID0gYWVzKHg9IHRpbWUpKSArIGdndGl0bGUoIkhvdyBPZnRlbiBCZXN0IEJ1eWluZyBUaW1lIGlzIHZzLiBUaW1lIEZyb20gR2FtZSIpCmBgYAoKIyBEb2VzIHRoZSBpbXBvcnRhbmNlIG9mIHRoZSBnYW1lIG1hdHRlciBpbiB0aGUgdG90YWwgYW1vdW50IG9mIHRyYWRlcz8KCmBgYHtyfQojVHJhbnNsYXRlIFJvdW5kIElECgpnZ3Bsb3QoYWxsc3B5ZGF0YSwgYWVzKHZvbHVtZSwgU3RhZ2UpKSArIGdlb21fYm94cGxvdCgpCmBgYAo=